#include "SNLBPEvaluator.h"
#include "opencv2\imgproc\imgproc.hpp"
//--------------------------------------------------------------

SNLBPEvaluator::SNLBPEvaluator()
{
}
//--------------------------------------------------------------

SNLBPEvaluator::~SNLBPEvaluator()
{
}
//--------------------------------------------------------------

void SNLBPEvaluator::Init(const SNFeatureParams* feature_params, int max_sample_count, cv::Size win_size)
{
	//CV_Assert(_maxSampleCount > 0);
	Sum.create(max_sample_count, (win_size.width + 1) * (win_size.height + 1), CV_32SC1);
	SNFeatureEvaluator::Init(feature_params, max_sample_count, win_size);
}
//--------------------------------------------------------------

void SNLBPEvaluator::SetImage(const cv::Mat& img, uchar cls_label, int idx)
{
	//CV_DbgAssert(!sum.empty());
	SNFeatureEvaluator::SetImage(img, cls_label, idx);
	cv::Mat inn_sum(WinSize.height + 1, WinSize.width + 1, Sum.type(), Sum.ptr<int>((int)idx));
	cv::integral(img, inn_sum);
}
//--------------------------------------------------------------

void SNLBPEvaluator::WriteFeatures(cv::FileStorage& fs, const cv::Mat& feature_map) const
{
	 fs << "features" << "[";
    const cv::Mat_<int>& featureMap_ = (const cv::Mat_<int>&)feature_map;
	for (int fi = 0; fi < feature_map.cols; fi++)
	{
		if (featureMap_(0, fi) >= 0)
		{
			fs << "{";
			Features[fi].Write(fs);
			fs << "}";
		}
	}
     
    fs << "]";
}
//--------------------------------------------------------------

void SNLBPEvaluator::GenerateFeatures()
{
	int offset = WinSize.width + 1;
	for (int x = 0; x < WinSize.width; x++)
	{
		for (int y = 0; y < WinSize.height; y++)
		{
			for (int w = 1; w <= WinSize.width / 3; w++)
			{
				for (int h = 1; h <= WinSize.height / 3; h++)
				{
					if ((x + 3 * w <= WinSize.width) && (y + 3 * h <= WinSize.height))
						Features.push_back(Feature(offset, x, y, w, h));
				}
			}
		}
	}
	
	NumFeatures = (int)Features.size();
}
//--------------------------------------------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------

uchar SNLBPEvaluator::Feature::Calc(const cv::Mat& _sum, size_t y) const
{
	const int* psum = _sum.ptr<int>((int)y);
	int cval = psum[p[5]] - psum[p[6]] - psum[p[9]] + psum[p[10]];

	return (uchar)((psum[p[0]] - psum[p[1]] - psum[p[4]] + psum[p[5]] >= cval ? 128 : 0) |   // 0
		(psum[p[1]] - psum[p[2]] - psum[p[5]] + psum[p[6]] >= cval ? 64 : 0) |    // 1
		(psum[p[2]] - psum[p[3]] - psum[p[6]] + psum[p[7]] >= cval ? 32 : 0) |    // 2
		(psum[p[6]] - psum[p[7]] - psum[p[10]] + psum[p[11]] >= cval ? 16 : 0) |  // 5
		(psum[p[10]] - psum[p[11]] - psum[p[14]] + psum[p[15]] >= cval ? 8 : 0) | // 8
		(psum[p[9]] - psum[p[10]] - psum[p[13]] + psum[p[14]] >= cval ? 4 : 0) |  // 7
		(psum[p[8]] - psum[p[9]] - psum[p[12]] + psum[p[13]] >= cval ? 2 : 0) |   // 6
		(psum[p[4]] - psum[p[5]] - psum[p[8]] + psum[p[9]] >= cval ? 1 : 0));     // 3
}
//--------------------------------------------------------------

SNLBPEvaluator::Feature::Feature()
{
	Rect = cvRect(0, 0, 0, 0);
}
//--------------------------------------------------------------

SNLBPEvaluator::Feature::Feature(int offset, int x, int y, int block_w, int block_h)
{
	cv::Rect tr = Rect = cvRect(x, y, block_w, block_h);

	SN_SUM_OFFSETS(p[0], p[1], p[4], p[5], tr, offset)
		tr.x += 2 * Rect.width;
	
	SN_SUM_OFFSETS(p[2], p[3], p[6], p[7], tr, offset)
		tr.y += 2 * Rect.height;

	SN_SUM_OFFSETS(p[10], p[11], p[14], p[15], tr, offset)
		tr.x -= 2 * Rect.width;

	SN_SUM_OFFSETS(p[8], p[9], p[12], p[13], tr, offset)
}
//--------------------------------------------------------------

void SNLBPEvaluator::Feature::Write(cv::FileStorage &fs) const
{
	fs << "rect" << "[:" << Rect.x << Rect.y << Rect.width << Rect.height << "]";
}
//--------------------------------------------------------------


